using System;
using GHIElectronics.NETMF.Hardware;
using GHIElectronics.NETMF.Net;
using GHIElectronics.NETMF.Net.Sockets;
using Microsoft.SPOT.Hardware;

namespace InternetThermostat.DeviceAccessor
{
    public class RealTimeClockAccessor
    {
        public static void InitializeClockToLocalTime(string NTPServer, int NTPOffsetInt)
        {
            // Probably still good since last check
            if (RealTimeClock.GetTime().Year > 2010)
                return;

            DateTime ntpDateTime = GetNTPTime(NTPServer, NTPOffsetInt);
            if (ntpDateTime != DateTime.MinValue)
            {
                Utility.SetLocalTime(ntpDateTime);
                RealTimeClock.SetTime(ntpDateTime);
            }
            else
            {
                throw new Exception("Error getting NTPTime");
            }

        }

        public static DateTime GetNTPTime(string timeServer, int gmtOffset = 0)
        {
            Socket s = null;
            try
            {
                // init socket
                EndPoint remoteEP = new IPEndPoint(Dns.GetHostEntry(timeServer).AddressList[0], 123);
                s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

                // init request
                byte[] ntpData = new byte[48];
                Array.Clear(ntpData, 0, 48);
                ntpData[0] = 0x1B; // set protocol version

                // send request
                s.SendTo(ntpData, remoteEP);

                // wait 30s if no response, timeout
                if (s.Poll(30 * 1000 * 1000, SelectMode.SelectRead))
                {
                    // get response
                    s.ReceiveFrom(ntpData, ref remoteEP);

                    s.Close();

                    // parse time value
                    byte offsetTransmitTime = 40;
                    ulong intpart = 0;
                    ulong fractpart = 0;
                    for (int i = 0; i <= 3; i++) intpart = (intpart << 8) | ntpData[offsetTransmitTime + i];
                    for (int i = 4; i <= 7; i++) fractpart = (fractpart << 8) | ntpData[offsetTransmitTime + i];
                    ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);

                    DateTime ntpTime = new DateTime(1900, 1, 1) + TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);

                    return ntpTime.AddMinutes(gmtOffset);
                }
                else
                {
                    // timeout
                    s.Close();
                }
            }
            catch (Exception e)
            {
                try
                {
                    s.Close();
                }
                catch { }
            }

            return DateTime.MinValue;
        }


    }
}
